package decaf.translate;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import decaf.tree.Tree;
import decaf.backend.OffsetCounter;
import decaf.symbol.Class;
import decaf.symbol.Function;
import decaf.symbol.Symbol;
import decaf.symbol.Variable;
import decaf.tac.Temp;

public class TransPass1 extends Tree.Visitor 
{
	private Translater tr;	//虚函数表 和 Functy表

	private int objectSize;	//object size

	private List<Variable> vars;	//成员变量表

	public TransPass1(Translater tr) 
	{
		this.tr = tr;
		vars = new ArrayList<Variable>();
	}

	@Override
	public void visitTopLevel(Tree.TopLevel program) 
	{
		for (Tree.ClassDef cd : program.classes) 
		{
			cd.accept(this);
		}
		for (Tree.ClassDef cd : program.classes) 
		{
			tr.createVTable(cd.symbol);	//创立虚函数表
			tr.genNewForClass(cd.symbol);	//不懂什么意思
		}
		for (Tree.ClassDef cd : program.classes) 
		{
			if (cd.parent != null) 
			{
				cd.symbol.getVtable().parent = cd.symbol.getParent().getVtable();
			}
		}
	}

	@Override
	public void visitClassDef(Tree.ClassDef classDef) 
	{
		classDef.symbol.resolveFieldOrder();	//不懂什么意思
		objectSize = 0;		//类大小初始化
		vars.clear();		//成员变量表初始化
		for (Tree f : classDef.fields) 
		{
			f.accept(this);
		}
		Collections.sort(vars, Symbol.ORDER_COMPARATOR);	//成员变量排序
		OffsetCounter oc = OffsetCounter.VARFIELD_OFFSET_COUNTER;	//oc.kind = Kind.VARFIELD
		Class c = classDef.symbol.getParent();
		if (c != null) 
		{
			oc.set(c.getSize());	//oc.value = c.size
		} 
		else 
		{
			oc.reset();	//oc.value = Kind.VARFIELD
		}
		for (Variable v : vars) 
		{
			v.setOffset(oc.next(OffsetCounter.WORD_SIZE));	//成员变量偏移量
		}
	}

	@Override
	public void visitMethodDef(Tree.MethodDef funcDef) 
	{
		Function func = funcDef.symbol;
		if (!func.isStatik()) 
		{
			func.setOffset(2 * OffsetCounter.POINTER_SIZE + func.getOrder() * OffsetCounter.POINTER_SIZE);
		}//成员函数偏移量
		tr.createFuncty(func);	//为Function创建Functy对象
		OffsetCounter oc = OffsetCounter.PARAMETER_OFFSET_COUNTER;
		oc.reset();	//oc.value = Kind.PARAMETER
		int order;
		if (!func.isStatik()) //若该成员函数不是静态的——引用非静态成员函数的必为局部变量
		{	
			Variable v = (Variable) func.getAssociatedScope().lookup("this");//为该对象实例的Temp（猜测）
			v.setOrder(0);
			Temp t = Temp.createTempI4();
			t.sym = v;
			t.isParam = true;//是变量
			v.setTemp(t);
			v.setOffset(oc.next(OffsetCounter.POINTER_SIZE));
			order = 1;
		} 
		else 
		{
			order = 0;
		}
		for (Tree.VarDef vd : funcDef.formals) 
		{
			vd.symbol.setOrder(order++);
			Temp t = Temp.createTempI4();	//创建Temp
			t.sym = vd.symbol;	//为Temp赋值
			t.isParam = true;	//是参数
			vd.symbol.setTemp(t);	//为形参关联Temp对象
			vd.symbol.setOffset(oc.next(vd.symbol.getTemp().size));	//形参偏移量
		}
	}

	@Override
	public void visitVarDef(Tree.VarDef varDef) 
	{
		vars.add(varDef.symbol);	//加入成员变量表
		objectSize += OffsetCounter.WORD_SIZE;	//计算类对象的大小
	}
}
